/*
 * Copyright 2010 Kevin L'Huillier <klhuillier@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.lhuillier.pwsafe.io.v3;


import org.lhuillier.pwsafe.io.DecryptionFailedException;
import org.lhuillier.pwsafe.io.RawDb;
import org.lhuillier.pwsafe.io.StretchedKey;
import org.lhuillier.pwsafe.io.codec.BinConverter;
import org.lhuillier.pwsafe.io.codec.RawDbDecoder;
import org.lhuillier.pwsafe.model.Database;
import com.google.inject.Inject;


class V3DbReaderImpl implements V3DbReader {
    private final Decrypt decrypt;
    private final BinToRaw binToRaw;
    private final RawDbDecoder rawDbDecode;
    private final BinConverter binConv;
    private final Crypto crypto;
    private final V3KeyStretcher stretcher;

    @Inject
    V3DbReaderImpl(Decrypt decrypt, BinToRaw rawReader,
            RawDbDecoder rawDbDecode, BinConverter binConv, 
            Crypto crypto, V3KeyStretcher stretcher) {
        this.decrypt = decrypt;
        this.binToRaw = rawReader;
        this.rawDbDecode = rawDbDecode;
        this.binConv = binConv;
        this.crypto = crypto;
        this.stretcher = stretcher;
    }

    @Override
    public Database load(byte[] data, StretchedKey key)
            throws DecryptionFailedException {
        return rawDbDecode.decode(loadRaw(data, key));
    }

    @Override
    public RawDb loadRaw(byte[] data, StretchedKey key)
            throws DecryptionFailedException {
        byte[] decrypted = decrypt.decrypt(data, key);
        return binToRaw.read(decrypted);
    }
    
    @Override
    public StretchedKey stretchKey(byte[] data, String password) {
        byte[] pwBytes = binConv.writeString(password);
        byte[] salt = binConv.slice(data, 4, 32);
        int iter = binConv.readInt(data, 36);
        byte[] enc = crypto.stretchKey(pwBytes, salt, iter);
        return new V3StretchedKey(enc, salt, iter, crypto, binConv, stretcher);
    }
}
